/**
 * @author mmbro
 * @homepage https://gitee.com/mmbro/
 * @date 2021年05月17日23:33:47
 * @description 注释:伪随机工具类
 */
RandomUtil = class RandomUtil {
    /**
     * @description 初始种子,必须大于1
     * @type {number}
     */
    #_seed = 1;
    /**
     * @description 随机数长度
     * @type {number}
     * @private
     */
    #_length = 100;

    /**
     * @description 构造方法
     * @param seed 随机数种子.若未指定,默认为1
     * @param length 随机数长度
     */
    constructor(seed, length) {
        this.#_seed = isNaN(seed) || seed < 1 ? RandomUtil.genId() : seed;
        this.#_length = isNaN(length) || length < 1 ? 100 : length;
        console.log('create RandomUtil, seed=%s,length=%s', this.#_seed, this.#_length);
    }

    /**
     * @description 获取伪随机 this.length 内的数字
     * @link https://blog.csdn.net/johnhany/article/details/8106564
     * @returns {number}
     */
    rand() {
        this.#_seed = (this.#_seed * 191 + 81) % this.#_length;
        return this.#_seed;
    }

    /**
     * @description 获取真随机 this.length 内的数字
     * @returns {number}
     */
    trueRand() {
        let rand = RandomUtil.genId() % this.#_length;
        return rand + 1;
    }

    /**
     * 计算随机数均衡分布样本
     * @param times 指定样本数量,默认长度的100倍
     * @returns {{rand: Map<any, any>, times: number, trueRand: Map<any, any>}}
     */
    testBalance(times = this.#_length * 100) {
        let functions = ['rand', 'trueRand'];
        let result = {times, rand: new Map(), trueRand: new Map()};
        functions.forEach(funName => {
            let arr = [];
            for (let i = 0; i < times; i++) {
                arr.push(this[funName]());
            }
            let spread = result[funName];
            arr.forEach(e => spread.set(e, !spread.get(e) ? 1 : 1 + spread.get(e)));
            let percent = [];
            spread.forEach((value, key) => percent.push({key, value, per: value / times}));
            percent.sort(SortUtil.numberDescSort((e) => e['per']));
            result[funName] = {spread, percent};
        })
        return result;
    }

    get seed() {
        return this.#_seed;
    }

    set seed(value) {
        this.#_seed = value;
    }

    get length() {
        return this.#_length;
    }

    set length(value) {
        this.#_length = value;
    }

    static genId() {
        let id = ('' + Math.random()).substr(2);
        id = StringUtil.newLength(id, 17, '0');
        return Number(id);
    }

    /**
     * 测试
     */
    static test() {
        let r = new RandomUtil();
        let result = r.testBalance(100);
        console.log(result);
    }
}